fix(core): [SDK Overhead Reduction 13] Preserve ISO8601 utility compatibility#5609
Open
adinauer wants to merge 2 commits into
Open
Conversation
Match edge-case behavior from the previous vendored ISO8601 utility for date-only timestamps, trailing characters after Z, and Gregorian cutover dates.
This was referenced Jun 23, 2026
Merged
📲 Install BuildsAndroid
|
Contributor
Performance metrics 🚀
|
Preserve ISO8601 parser compatibility for date-only values that include a timezone suffix. Keep modern date-only timezone parsing on the fast path and add parity coverage against the previous parser.
| return epochMillis(year, month, day, 0, 0, 0, 0, 0); | ||
| throw new IllegalArgumentException("Invalid date separator"); | ||
| } | ||
| validateDate(year, month, day); |
There was a problem hiding this comment.
Bug: SentryIso8601Utils.parseTimestamp() incorrectly validates pre-Gregorian dates. It applies Gregorian leap year rules before the 1582 cutover, rejecting valid Julian leap year dates like '0200-02-29'.
Severity: LOW
Suggested Fix
The validation logic should be corrected to account for the Julian calendar for dates before the Gregorian cutover (October 15, 1582). Instead of performing a separate validateDate check upfront with Gregorian rules, the parsing should rely on a calendar implementation that correctly handles the historical calendar transition, similar to the previous utility.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: sentry/src/main/java/io/sentry/vendor/SentryIso8601Utils.java#L51
Potential issue: The date validation logic in `SentryIso8601Utils.parseTimestamp()`
introduces a regression for pre-Gregorian dates. When parsing a timestamp like
"0200-02-29T00:00:00.000Z", the `validateDate(200, 2, 29)` call at line 51 uses
`isLeapYear(200)`. This function incorrectly returns `false` because it applies
proleptic Gregorian rules, where 200 is not a leap year. Consequently, `validateDate`
throws an `IllegalArgumentException`, assuming February has only 28 days. The previous
implementation correctly handled this by using `GregorianCalendar`, which applies Julian
calendar rules for dates before the 1582 cutover, where the year 200 is a leap year.
Did we get this right? 👍 / 👎 to inform future reviews.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Stack (SDK Overhead Reduction)
📜 Description
Preserves edge-case behavior from the previous vendored
ISO8601Utilswhile keeping the fast Sentry ISO-8601 timestamp utility from the base PR.This covers date-only timestamps, trailing characters after
Z, and dates around the Gregorian calendar cutover. It also adds direct comparison tests against the previous vendored utility for parsing and formatting behavior.💡 Motivation and Context
The base ISO-8601 utility replacement optimizes hot timestamp parsing and formatting paths. These changes make the replacement safer by locking down compatibility with the previous utility for less common inputs that can still arrive through cached envelopes, native/hybrid payloads, or user-provided serialized data.
💚 How did you test it?
./gradlew :sentry:test --tests io.sentry.DateUtilsTest./gradlew spotlessApply apiDump📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps
#skip-changelog